udev针对Linux内核2.6及更高版本,以持久的设备命名为动态/ dev目录提供用户空间解决方案。现在不建议使用以前的/ dev实现devfs,而将udev视为后继。udev vs devfs是一个非常敏感的话题-您应该在进行比较之前阅读本文档。
多年来,您可能会使用udev规则的事情以及规则本身的灵活性已经发生了变化。在现代系统上,udev为某些设备类型提供了现成的持久命名功能,从而无需为这些设备自定义规则。但是,某些用户仍然需要额外的自定义级别。
本文假定您已安装udev并以默认配置运行正常。这通常由Linux发行版处理。
本文档并未涵盖规则编写的每个细节,但旨在介绍所有主要概念。可以在udev手册页中找到更详细的信息。
本文档使用各种示例(其中许多示例完全是虚构的)来说明思想和概念。并非所有语法都在随附的文本中明确描述,请务必查看示例规则以获得完整的了解。
仅是基本介绍,可能并不完全准确。
在典型的基于Linux的系统上,/ dev目录用于存储类似于文件的设备节点,这些节点引用系统中的某些设备。每个节点都指向系统(设备)的一部分,该部分可能存在或可能不存在。用户空间应用程序可以使用这些设备节点与系统硬件进行接口,例如,X服务器将“监听” / dev / input / mice,以便它可以将用户的鼠标移动与可视鼠标指针移动相关联。
原始的/ dev目录只是填充了系统中可能出现的每个设备。因此,/ dev目录通常很大。devfs的出现是为了提供一种更易于管理的方法(值得注意的是,它仅使用插入系统的硬件来填充/ dev)以及其他一些功能,但是事实证明该系统存在无法轻易修复的问题。
udev是管理/ dev目录的“新”方式,旨在清除以前的/ dev实现中的一些问题,并提供可靠的前进途径。为了创建和名称的/ dev对应于存在于所述系统中的设备设备节点,udev的依赖于所提供的匹配信息的sysfs与规则由用户提供。本文档旨在详细说明规则编写的过程,这是用户必须(可选)执行的仅有的与udev相关的任务之一。
sysfs是2.6内核的新文件系统。它由内核管理,并导出有关当前插入系统的设备的基本信息。udev可以使用此信息来创建与您的硬件相对应的设备节点。sysfs安装在/ sys上并且可以浏览。在使用udev之前,您可能希望研究其中存储的一些文件。在整个文档中,我将交替使用术语/ sys和sysfs。
udev规则灵活且功能强大。您可以使用规则来实现以下一些目的:
对于您的特定设备不存在任何设备节点的问题, 编写规则不是解决方法。即使没有匹配的规则,udev也会使用内核提供的默认名称创建设备节点。
具有永久命名的设备节点具有多个优点。假设您拥有两个USB存储设备:数码相机和USB闪存盘。这些设备通常被分配了设备节点/ dev / sda和/ dev / sdb,但是确切的分配取决于它们最初连接的顺序。这可能会给某些用户带来问题,如果每次可以永久性地命名每个设备(例如/ dev / camera和/ dev / flashdisk),这些用户将受益匪浅。
udev开箱即用为某些设备类型提供持久命名。这是一个非常有用的功能,并且在许多情况下意味着您的旅程在这里结束:您不必编写任何规则。
udev为/ dev / disk目录中的存储设备提供了开箱即用的持久命名。要查看为存储硬件创建的永久名称,可以使用以下命令:
#ls -lR / dev / disk
这适用于所有存储类型。例如,udev创建了/ dev / disk / by-id / scsi-SATA_ST3120827AS_4MS1NDXZ-part3,这是到我的根分区的永久命名符号链接。当我插入USB闪存盘时,udev会创建/dev/disk/by-id/usb-Prolific_Technology_Inc._USB_Mass_Storage_Device-part1,这也是一个永久名称。
在决定如何命名设备以及要执行的其他操作时,udev会读取一系列规则文件。这些文件保存在/etc/udev/rules.d目录中,并且都必须带有.rules后缀。
默认的udev规则存储在/etc/udev/rules.d/50-udev.rules中。查看该文件可能会很有趣-它包含一些示例,然后提供一些证明devfs风格的/ dev布局的默认规则。但是,您不应直接将规则写入此文件。
/etc/udev/rules.d/中的文件以词法顺序进行解析,在某些情况下,规则的解析顺序非常重要。通常,您希望在默认值之前先解析自己的规则,因此建议您在/etc/udev/rules.d/10-local.rules中创建一个文件,并将所有规则写入此文件中。
在规则文件中,以“#”开头的行被视为注释。所有其他非空白行都是规则。规则不能跨越多行。
一台设备可以通过多个规则进行匹配。这具有实际的优势,例如,我们可以编写与同一设备匹配的两个规则,其中每个规则为设备提供自己的备用名称。即使规则位于单独的文件中,也会创建两个备用名称。重要的是要了解,udev 在找到匹配的规则时不会停止处理,它将继续搜索并尝试应用它知道的每个规则。
每个规则都是由一系列键值对构成的,这些键值对之间用逗号分隔。匹配键是用于识别规则所依据的设备的条件。当规则中的所有匹配键都与要处理的设备相对应时,将应用该规则并调用分配键的操作。每个规则应至少包含一个匹配键和至少一个分配键。
这是一个示例规则来说明上述内容:
KERNEL ==“ hdb”,NAME =“ my_spare_disk”
上面的规则包括一个匹配键(KERNEL)和一个分配键(NAME)。这些键的语义及其属性将在后面详细介绍。重要的是要注意,匹配键通过相等运算符(==)与它的值相关,而分配键通过赋值运算符(=)与它的值相关。
请注意,udev不支持任何形式的行继续。请勿在规则中插入任何换行符,因为这会使udev将您的一个规则视为多个规则,并且无法按预期工作。
udev提供了几种不同的匹配键,可用于编写非常精确地匹配设备的规则。下面介绍了一些最常用的键,另一些将在本文档的后面介绍。有关完整列表,请参见udev手册页。
使用一系列匹配键精确匹配设备后,udev可通过一系列分配键使您对接下来发生的事情进行精细控制。有关可能的分配键的完整列表,请参见udev手册页。下面介绍最基本的分配键。其他内容将在本文档后面介绍。
如上所述,udev只为一台设备创建一个真实的设备节点。如果希望为此设备节点提供备用名称,请使用符号链接功能。使用SYMLINK分配,您实际上是在维护一个符号链接列表,所有这些链接都将指向实际设备节点。为了操纵这些链接,我们引入了一个新的运算符,用于追加到列表:+ =。您可以将任意一条规则的多个符号链接附加到列表中,方法是将每个规则用空格隔开。
KERNEL ==“ hdb”,NAME =“ my_spare_disk”
上面的规则说:匹配由内核命名为hdb的设备,而不是将其称为hdb,将设备节点命名为my_spare_disk。设备节点显示在/ dev / my_spare_disk上。
KERNEL ==“ hdb”,DRIVER ==“ ide-disk”,SYMLINK + =“备用磁盘”
上面的规则说:匹配一个被内核命名为hdb AND的设备,其中驱动程序是ide-disk。使用默认名称命名设备节点,并创建一个到其的符号链接,命名为sparedisk。请注意,我们未指定设备节点名称,因此udev使用默认名称。为了保留标准的/ dev布局,您自己的规则通常会将NAME 保留下来,但会创建一些SYMLINK和/或执行其他分配。
KERNEL ==“ hdc”,SYMLINK + =“ cdrom cdrom0”
上面的规则可能是您正在编写的规则类型中更典型的。它在/ dev / cdrom和/ dev / cdrom0处创建两个符号链接,它们都指向/ dev / hdc。同样,未指定任何NAME分配,因此使用默认内核名称(hdc)。
到目前为止引入的匹配键仅提供有限的匹配功能。实际上,我们需要更好的控制:我们希望基于高级属性(例如供应商代码,确切的产品编号,序列号,存储容量,分区数量等)来识别设备。
许多驱动程序将这样的信息导出到sysfs中,而udev允许我们使用ATTR键(语法略有不同)将sysfs-matching纳入我们的规则中。
这是与sysfs中的单个属性匹配的示例规则。本文档后面将提供更多详细信息,这将帮助您根据sysfs属性编写规则。
SUBSYSTEM ==“ block”,ATTR {size} ==“ 234441648”,SYMLINK + =“ my_disk”
Linux内核实际上以树状结构表示设备,该信息通过sysfs公开,在编写规则时很有用。例如,我的硬盘设备的设备表示是SCSI磁盘设备的子设备,而后者又是串行ATA控制器设备的子设备,而后者又是PCI总线设备的子设备。您可能会发现自己需要参考相关设备的父级提供的信息,例如,我的硬盘设备的序列号未在设备级别公开,而是由其直接父级在SCSI中公开的磁盘级别。
到目前为止,引入的四个主要匹配键(KERNEL / SUBSYSTEM / DRIVER / ATTR)仅与对应于所讨论设备的值匹配,而与父设备的值不匹配。udev提供了将在树中向上搜索的匹配键的变体:
考虑到层次结构的考虑,您可能会觉得规则编写变得有些复杂。请放心,这里有帮助的工具,稍后将介绍。
在编写可能处理多个相似设备的规则时,udev的类似于printf的字符串替换运算符非常有用。您可以简单地将这些运算符包括在规则进行的任何分配中,udev会在执行它们时对其进行评估。
最常见的运算符是%k和%n。%k计算设备的内核名称,例如,设备的“ sda3”(默认情况下)将出现在/ dev / sda3。%n计算设备的内核号(存储设备的分区号),例如/ dev / sda3的值为“ 3” 。
udev还提供了其他几个替代运算符,以提供更多高级功能。阅读完本文档的其余部分后,请查阅udev手册页。这些运算符还有另一种语法- 上述示例中的$ kernel和$ number。因此,如果要在规则中匹配文字%,则必须写%%;如果要匹配文字$,则必须写$$。
为了说明字符串替换的概念,下面显示了一些示例规则。
KERNEL ==“鼠标”,NAME =“输入/%k” KERNEL ==“ loop0”,NAME =“ loop /%n”,SYMLINK + =“%k”
第一条规则确保mouses设备节点专门出现在/ dev / input目录中(默认情况下,它位于/ dev / mice)。第二条规则确保在/ dev / loop / 0处创建了名为loop0的设备节点,并且照常在/ dev / loop0处创建了符号链接。
上述规则的使用值得怀疑,因为它们都可以在不使用任何替换运算符的情况下进行重写。这些替代的真正力量将在下一部分中变得明显。
除了精确匹配字符串外,udev还允许您使用外壳样式的模式匹配。支持3种模式:
这里是一些包含以上模式的示例。注意使用字符串替换运算符。
KERNEL ==“ fd [0-9] *”,NAME =“ floppy /%n”,SYMLINK + =“%k” KERNEL ==“ hiddev *”,NAME =“ usb /%k”
第一条规则匹配所有软盘驱动器,并确保将设备节点放置在/ dev / floppy目录中,并确保使用默认名称创建符号链接。第二条规则确保hiddev设备仅存在于/ dev / usb目录中。
上面简要介绍了使用来自sysfs的有趣信息的概念。为了基于此信息编写规则,您首先需要知道属性的名称及其当前值。
sysfs实际上是一个非常简单的结构。它在逻辑上分为目录。每个目录包含许多文件(属性),通常只包含一个值。存在一些符号链接,这些符号链接将设备链接到其父母。层次结构已在上面提到。
有些目录称为顶级设备路径。这些目录代表具有相应设备节点的实际设备。顶级设备路径可以归类为sysfs目录,其中包含一个dev文件,以下命令将为您列出这些目录:
#查找/ sys -name dev
例如,在我的系统上,/ sys / block / sda目录是我的硬盘的设备路径。它通过/ sys / block / sda / device符号链接链接到其父SCSI磁盘设备。
当您基于sysfs信息编写规则时,您只是在链的一部分中匹配某些文件的属性内容。例如,我可以读取硬盘的大小,如下所示:
#猫/ sys / block / sda / size 234441648
在udev规则中,我可以使用ATTR {size} ==“ 234441648”标识此磁盘。当udev遍历整个设备链时,我可以选择使用ATTRS来匹配链另一部分中的属性(例如/ sys / class / block / sda / device /中的属性),但是在处理不同的属性时有一些注意事项链条的各个部分,将在后面进行介绍。
尽管这是对sysfs的结构以及udev确切如何与值匹配的有用介绍,但是手动拖曳sysfs既费时又不必要。
输入udevinfo,它可能是您可以用来构建规则的最直接的工具。您需要知道的只是所讨论设备的sysfs设备路径。修剪的示例如下所示:
#udevinfo -a -p / sys / block / sda 查看设备'/ block / sda': KERNEL ==“ sda” SUBSYSTEM ==“块” ATTR {stat} ==“ 128535 2246 2788977 766188 73998 317300 3132216 5735004 0 516516 6503316” ATTR {size} ==“ 234441648” ATTR {removable} ==“ 0” ATTR {range} ==“ 16” ATTR {dev} ==“ 8:0” 查看父设备'/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0': KERNELS ==“ 0:0:0:0” SUBSYSTEMS ==“ scsi” DRIVERS ==“ sd” ATTRS {ioerr_cnt} ==“ 0x0” ATTRS {iodone_cnt} ==“ 0x31737” ATTRS {iorequest_cnt} ==“ 0x31737” ATTRS {iocounterbits} ==“ 32” ATTRS {timeout} ==“ 30” ATTRS {state} ==“正在运行” ATTRS {rev} ==“ 3.42” ATTRS {model} ==“ ST3120827AS” ATTRS {vendor} ==“ ATA” ATTRS {scsi_level} ==“ 6” ATTRS {type} ==“ 0” ATTRS {queue_type} ==“ none” ATTRS {queue_depth} ==“ 1” ATTRS {device_blocked} ==“ 0” 查看父设备“ /devices/pci0000:00/0000:00:07.0”: KERNELS ==“ 0000:00:07.0” SUBSYSTEMS ==“ pci” DRIVERS ==“ sata_nv” ATTRS {vendor} ==“ 0x10de” ATTRS {device} ==“ 0x037f”
如您所见,udevinfo只是生成一系列属性,您可以按原样使用它们作为udev规则中的匹配键。从上面的示例中,我可以为此设备生成(例如)以下两个规则之一:
SUBSYSTEM ==“ block”,ATTR {size} ==“ 234441648”, NAME =“ my_hard_disk” SUBSYSTEM ==“ block”,SUBSYSTEMS ==“ scsi”,ATTRS {model} ==“ ST3120827AS”, NAME =“ my_hard_disk ”
您可能已经在上面的示例中注意到了颜色的使用。这是为了证明将相关设备的属性和单个父设备的属性组合在一起是合法的,但您不能混合匹配多个父设备的属性-您的规则将不起作用。例如,以下规则无效,因为它试图匹配两个父设备的属性:
SUBSYSTEM ==“ block”,ATTRS {model} ==“ ST3120827AS”,DRIVERS ==“ sata_nv”,NAME =“ my_hard_disk”
通常会为您提供大量的属性,并且必须选择其中的一些属性来构建规则。通常,您希望选择以持久且人类可识别的方式识别设备的属性。在上面的示例中,我选择了磁盘的大小及其型号。我没有使用无意义的数字,例如ATTRS {iodone_cnt} ==“ 0x31737”。
在udevinfo输出中观察层次结构的影响。与该设备相对应的绿色部分使用标准匹配键,例如KERNEL和ATTR。对应于父级设备的蓝色和栗色部分使用父级遍历变量,例如SUBSYSTEMS和ATTRS。这就是为什么分层结构引入的复杂性实际上很容易处理的原因,只需确保使用udevinfo建议的确切值即可。
还要注意的另一点是,文本属性通常出现在udevinfo输出中,并用空格填充(例如,参见上面的ST3120827AS)。在您的规则中,您可以指定多余的空格,也可以像我一样将其切除。
使用udevinfo的唯一麻烦在于,您需要了解顶级设备路径(在上例中为/ sys / block / sda)。这并不总是很明显。但是,由于通常是为已经存在的设备节点编写规则,因此可以使用udevinfo为您查找设备路径:
#udevinfo -a -p $(udevinfo -q path -n / dev / sda)
尽管udevinfo几乎肯定是列出可以从中构建规则的确切属性的最直接方法,但是有些用户对其他工具更满意。诸如usbview之类的实用工具会显示一组相似的信息,其中大多数信息都可以在规则中使用。
udev允许您在规则中使用其他分配来控制每个设备上的所有权和权限属性。
该集团分配允许您定义的Unix组应该拥有的设备节点。以下是一个示例规则,该规则定义了视频组将拥有帧缓冲设备:
KERNEL ==“ fb [0-9] *”,NAME =“ fb /%n”,SYMLINK + =“%k”,GROUP =“ video”
该OWNER关键,或许用处不大,允许您定义Unix用户应该有设备节点所有权权限。假设您希望john拥有您的软盘设备,这有点奇怪,您可以使用:
KERNEL ==“ fd [0-9] *”,OWNER =“ john”
udev默认使用Unix权限0660(对所有者和组进行读/写)创建节点。如果需要,您可以使用包括MODE分配在内的规则在某些设备上覆盖这些默认设置。例如,以下规则定义了inotify节点对所有人都是可读可写的:
KERNEL ==“ inotify”,NAME =“ misc /%k”,SYMLINK + =“%k”,MODE =“ 0666”
在某些情况下,您可能需要比标准udev规则所提供的更多的灵活性。在这种情况下,您可以要求udev运行一个程序,并使用该程序的标准输出来提供设备命名。
要使用此功能,只需在PROGRAM分配中指定要运行的程序的绝对路径(以及任何参数),然后在NAME / SYMLINK分配中使用%c替换的某种变体。
以下示例引用了在/ bin / device_namer上找到的虚构程序。device_namer采用一个命令行参数,该命令行参数是设备的内核名称。基于该内核名称,device_namer发挥了作用,并向通常的stdout管道生成了一些输出,并分成了几个部分。每个部分只是一个单词,各个部分之间用一个空格隔开。
在我们的第一个示例中,我们假设device_namer输出许多部分,每个部分形成所涉及设备的符号链接(替代名称)。
KERNEL ==“ hda”,PROGRAM =“ / bin / device_namer%k”,SYMLINK + =“%c”
下一个示例假定device_namer输出两部分,第一部分是设备名称,第二部分是其他符号链接的名称。现在,我们引入%c {N}替换,它表示输出的N部分:
KERNEL ==“ hda”,PROGRAM =“ / bin / device_namer%k”,NAME =“%c {1}”,SYMLINK + =“%c {2}”
下一个示例假定device_namer输出一个部分作为设备名称,然后输出任意数量的部分,这些部分将形成附加的符号链接。现在,我们介绍%c {N +}替换,该替换的计算结果为N,N + 1,N + 2等,直到输出结束。
KERNEL ==“ hda”,PROGRAM =“ / bin / device_namer%k”,NAME =“%c {1}”,SYMLINK + =“%c {2+}”
输出部分可以在任何分配键中使用,不仅可以使用NAME和SYMLINK。下面的示例使用一个虚构的程序来确定应该拥有该设备的Unix组:
KERNEL ==“ hda”,PROGRAM =“ / bin / who_owns_device%k”,GROUP =“%c”
编写udev规则的另一个原因是在设备连接或断开连接时运行特定程序。例如,您可能需要执行脚本以在连接数码相机后自动从数码相机下载所有照片。
请勿将其与上述PROGRAM功能混淆。PROGRAM用于运行产生设备名称的程序(除此之外,它们不应做任何其他事情)。在执行这些程序时,尚未创建设备节点,因此无法以任何方式对设备进行操作。
此处介绍的功能允许您在放置设备节点后运行程序。该程序可以在设备上运行,但是不能在任何长时间内运行,因为在这些程序运行时udev会有效地暂停。解决此限制的一种方法是确保程序立即自行分离。
这是一个示例规则,演示了RUN列表分配的用法:
KERNEL ==“ sdb”,RUN + =“ / usr / bin / my_program”
当在/ usr /斌/ MY-被执行时,udev的环境的各部分可作为环境变量,包括如键值SUBSYSTEM。您还可以使用ACTION环境变量来检测设备是处于连接状态还是已断开连接-ACTION分别为“添加”或“删除”。
udev不会在任何活动终端上运行这些程序,并且不会在shell上下文中执行它们。确保确保您的程序被标记为可执行文件,如果它是Shell脚本,请确保它以适当的shebang(例如#!/bin/sh)开头,并且不要期望任何标准输出出现在终端上。
udev 为环境变量提供了一个ENV密钥,可用于匹配和分配。
在分配情况下,您可以设置环境变量,以后可以将其与之匹配。您还可以设置环境变量,这些环境变量可以由使用上述技术调用的任何外部程序使用。设置环境变量的虚拟示例规则如下所示。
KERNEL ==“ fd0”,SYMLINK + =“ floppy”,ENV {some_var} =“ value”
在匹配的情况下,您可以确保规则仅根据环境变量的值运行。请注意,udev看到的环境将与您在控制台上看到的环境不同。涉及环境匹配的虚拟规则如下所示。
KERNEL ==“ fd0”,ENV {an_env_var} ==“是”,SYMLINK + =“软盘”
如果在udev的环境中将$ an_env_var设置为“ yes”,则 上述规则仅创建/ dev / floppy链接。
另一项可以证明有用的作业是“ 选项”列表。有一些选项:
例如,以下规则在我的硬盘节点上设置组所有权,并确保以后的任何规则都不会起作用:
KERNEL ==“ sda”,GROUP =“ disk”,OPTIONS + =“ last_rule”
我打开打印机电源,并为其分配了设备节点/ dev / lp0。我对这样的乏味名称不满意,因此决定使用udevinfo来帮助我编写一条规则,以提供替代名称:
#udevinfo -a -p $(udevinfo -q path -n / dev / lp0)
查看设备'/ class / usb / lp0':
内核==“ lp0”
SUBSYSTEM ==“ usb”
驾驶员==“”
ATTR {dev} ==“ 180:0”
查看父设备'/devices/pci0000:00/0000:00:1d.0/usb1/1-1':
SUBSYSTEMS ==“ usb”
ATTRS {manufacturer} ==“ EPSON”
ATTRS {product} ==“ USB打印机”
ATTRS {serial} ==“ L72010011070626380”
我的规则变成:
SUBSYSTEM ==“ usb”,ATTRS {serial} ==“ L72010011070626380”,SYMLINK + =“ epson_680”
像大多数相机一样,我的相机使用SCSI传输将自己标识为通过USB总线连接的外部硬盘。要访问我的照片,我安装了驱动器并将图像文件复制到硬盘上。
并非所有相机都以这种方式工作:其中一些相机使用非存储协议,例如gphoto2支持的相机。在gphoto的情况下,您不希望为设备编写规则,因为它仅由用户空间(而不是特定的内核驱动程序)控制。
USB摄像头设备的常见并发症是它们通常将自己标识为具有单个分区的磁盘,在本例中为/ dev / sdb和/ dev / sdb1。sdb节点对我没有用,但是sdb1很有趣-这是我要安装的节点。这里存在一个问题,因为sysfs已链接,所以udevinfo为/ dev / sdb1生成的有用属性与/ dev / sdb的有用属性相同。这将导致您的规则可能与原始磁盘和分区都匹配,这不是您想要的,因此您的规则应特定。
为了解决这个问题,您只需要考虑sdb和sdb1之间的区别。这非常简单:名称本身有所不同,因此我们可以在NAME字段上使用简单的模式匹配。
#udevinfo -a -p $(udevinfo -q path -n / dev / sdb1)
查看设备'/ block / sdb / sdb1':
内核==“ sdb1”
SUBSYSTEM ==“块”
查看父设备'/devices/pci0000:00/0000:00:02.1/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':
KERNELS ==“ 6:0:0:0”
SUBSYSTEMS ==“ scsi”
DRIVERS ==“ sd”
ATTRS {rev} ==“ 1.00”
ATTRS {model} ==“ X250,D560Z,C350Z”
ATTRS {vendor} ==“ OLYMPUS”
ATTRS {scsi_level} ==“ 3”
ATTRS {type} ==“ 0”
我的规则:
KERNEL ==“ sd?1”,SUBSYSTEMS ==“ scsi”,ATTRS {model} ==“ X250,D560Z,C350Z”,SYMLINK + =“ camera”
USB硬盘与我上面描述的USB相机相当,但是典型的使用模式是不同的。在摄像机示例中,我解释说我对sdb节点不感兴趣-唯一真正的用途是进行分区(例如,使用fdisk),但是为什么要对摄像机进行分区!
当然,如果您有一个100GB的USB硬盘,可以对它进行分区是完全可以理解的,在这种情况下,我们可以利用udev的字符串替换:
KERNEL ==“ sd *”,SUBSYSTEMS ==“ scsi”,ATTRS {model} ==“ USB 2.0存储设备”,SYMLINK + =“ usbhd%n”
此规则创建符号链接,例如:
USB读卡器(CompactFlash,SmartMedia等)是另一种具有不同使用要求的USB存储设备。
这些设备通常不会在媒体更改时通知主机。因此,如果您在没有介质的情况下插入设备,然后插入卡,则计算机将无法实现,并且该介质没有可安装的sdb1分区节点。
一种可能的解决方案是利用all_partitions选项,该选项将为该规则匹配的每个块设备创建16个分区节点:
KERNEL =“ sd *”,SUBSYSTEMS ==“ scsi”,ATTRS {model} ==“ USB 2.0 CompactFlash读取器”,SYMLINK + =“ cfrdr%n”,OPTIONS + =“ all_partitions”
现在,您将拥有名为:cfrdr,cfrdr1,cfrdr2,cfrdr3,...,cfrdr15的节点。
这些设备充当USB串行设备,因此默认情况下,您仅获得ttyUSB1设备节点。palm实用程序依赖/ dev / pilot,因此许多用户将希望使用规则来提供此功能。
Carsten Clasohm的博客文章似乎是此的权威来源。卡斯滕的规则如下所示:
SUBSYSTEMS ==“ usb”,ATTRS {product} ==“掌上电脑”,KERNEL ==“ ttyUSB *”,SYMLINK + =“飞行员”
请注意,产品字符串似乎因产品而异,因此请确保(使用udevinfo)检查适用于您的字符串。
这台计算机中有两个光驱:DVD读取器(hdc)和DVD重写器(hdd)。我不希望这些设备节点发生更改,除非我重新物理连接了系统。但是,为了方便起见,许多用户喜欢使用设备节点(例如/ dev / dvd)。
我们知道这些设备的内核名称,因此规则编写很简单。这是我的系统的一些示例:
SUBSYSTEM ==“ block”,KERNEL ==“ hdc”,SYMLINK + =“ dvd”,GROUP =“ cdrom” SUBSYSTEM ==“ block”,KERNEL ==“ hdd”,SYMLINK + =“ dvdrw”,GROUP =“ cdrom”
即使通过名称引用它们,网络接口通常也没有与之关联的设备节点。尽管如此,规则编写过程几乎是相同的。
只需在规则中匹配接口的MAC地址是有意义的,因为这是唯一的。但是,请确保使用如udevinfo所示的确切 MAC地址,因为如果大小写不完全匹配,则规则将不起作用。
#udevinfo -a -p / sys / class / net / eth0
查看类设备“ / sys / class / net / eth0”:
内核==“ eth0”
ATTR {address} ==“ 00:52:8b:d5:04:48”
这是我的规则:
KERNEL ==“ eth *”,ATTR {address} ==“ 00:52:8b:d5:04:48”,NAME =“ lan”
您将需要重新加载网络驱动程序,此规则才能生效。您可以卸载并重新加载模块,也可以简单地重新引导系统。您还需要将系统重新配置为使用“ lan”而不是“ eth0”。在将所有对eth0的引用完全删除之前,我遇到了一些麻烦(接口未重命名)。在那之后,您应该能够在对ifconfig或类似实用程序的任何调用中使用“ lan”而不是“ eth0”。
假设您使用的是inotify支持的最新内核,udev将自动监视您的规则目录并自动获取您对规则文件所做的任何修改。
尽管如此,udev不会自动重新处理所有设备并尝试应用新规则。例如,如果编写规则在插入相机时为相机添加额外的符号链接,则不能期望额外的符号链接立即显示。
要显示符号链接,可以断开并重新连接相机,或者在不可移动设备的情况下,可以运行udevtrigger。
如果您的内核不支持inotify,则不会自动检测到新规则。在这种情况下,必须对规则文件进行任何修改,然后才能运行udevcontrol reload_rules,这些修改才能生效。
如果您知道sysfs中的顶级设备路径,则可以使用udevtest显示udev将采取的操作。这可以帮助您调试规则。例如,假设您要调试对/ sys / class / sound / dsp起作用的规则:
#udevtest / class / sound / dsp 主要:从子系统“声音”中查看设备“ / class / sound / dsp” udev_rules_get_name:添加符号链接“ dsp” udev_rules_get_name:已应用规则,“ dsp”变为“声音/ dsp” udev_device_event:设备'/ class / sound / dsp'已知,删除可能的符号链接 udev_node_add:创建设备节点'/ dev / sound / dsp',major ='14',minor ='3',mode ='0660',uid ='0',gid ='18' udev_node_add:创建符号链接'/ dev / dsp'到'sound / dsp'
请注意,/ sys前缀已从udevtest命令行参数中删除,这是因为udevtest在设备路径上运行。还要注意,udevtest纯粹是一种测试/调试工具,尽管输出表明,它也不会创建任何设备节点!
本文档由Daniel Drake < dan@reactivated.net > 撰写。反馈表示赞赏。
为了获得支持,您应该邮寄linux-hotplug邮件列表:linux-hotplug-devel@lists.sourceforge.net。
版权所有(C)2003-2006 Daniel Drake。
本文档根据GNU通用公共许可证第2版获得许可。